#include <stdio.h>
#include <iostream>
#include <vector>
#include <utility>
#include "comp.h"
#include "feature.h"
#include <math.h>

using namespace std;

FEATURE::FEATURE(const COMP_RECT &rect)
{
	int x1, x2, y1, y2;

	width = rect.width;
	height = rect.height;
	FEATURE::rect = rect;
	x1 = rect.width / 3;
	x2 = rect.width * 2 / 3;
	y1 = rect.height / 3;
	y2 = rect.height * 2 / 3;

	cout << "x1=" << x1 << endl;
	cout << "x2=" << x2 << endl;
	cout << "y1=" << y1 << endl;
	cout << "y2=" << y2 << endl;

	int i;
	int num = 0;

	//feature[0] = 0;
	for (i = 0; i < y1; i++) {
		for (int j = 0; j < x1; j++) {
			if (rect.rect[i * rect.width + j] == '0')
				num++;
		}
	}
	feature.push_back(num);

	num = 0;
	//feature[1] = 0;
	for (i = 0; i < y1; i++) {
		for (int j = x1; j < x2; j++) {
			if (rect.rect[i * rect.width + j] == '0')
				num++;
		}
	}
	feature.push_back(num);

	//feature[2] = 0;
	num = 0;
	for (i = 0; i < y1; i++) {
		for (int j = x2; j < rect.width; j++) {
			if (rect.rect[i * rect.width + j] == '0')
				num++;
		}
	}
	feature.push_back(num);

	//feature[3] = 0;
	num = 0;
	for (i = y1; i < y2; i++) {
		for (int j = 0; j < x1; j++) {
			if (rect.rect[i * rect.width + j] == '0')
				num++;
		}
	}
	feature.push_back(num);
	
	//feature[4] = 0;
	num = 0;
	for (i = y1; i < y2; i++) {
		for (int j = x1; j < x2; j++) {
			if (rect.rect[i * rect.width + j] == '0')
				num++;
		}
	}
	feature.push_back(num);
	
	//feature[5] = 0;
	num = 0;
	for (i = y1; i < y2; i++) {
		for (int j = x2; j < rect.width; j++) {
			if (rect.rect[i * rect.width + j] == '0')
				//feature[5]++;
				num++;
		}
	}
	feature.push_back(num);
	
	//feature[6] = 0;
	num = 0;
	for (i = y2; i < rect.height; i++) {
		for (int j = 0; j < x1; j++) {
			if (rect.rect[i * rect.width + j] == '0')
				num++;
		}
	}
	feature.push_back(num);
	
	//feature[7] = 0;
	num = 0;
	for (i = y2; i < rect.height; i++) {
		for (int j = x1; j < x2; j++) {
			if (rect.rect[i * rect.width + j] == '0')
				num++;
		}
	}
	feature.push_back(num);
	
	//feature[8] = 0;
	num = 0;
	for (i = y2; i < rect.height; i++) {
		for (int j = x2; j < rect.width; j++) {
			if (rect.rect[i * rect.width + j] == '0')
				num++;
		}
	}
	feature.push_back(num);

	//feature[9] = 0;
	num = 0;
	for (i = 0; i < rect.width; i++) {
		if (rect.rect[y1 * rect.width + i] == '0')
			num++;
	}
	feature.push_back(num);
	
	//feature[10] = 0;
	num = 0;
	for (i = 0; i < rect.width; i++) {
		if (rect.rect[y2 * rect.width + i] == '0')
			num++;
	}
	feature.push_back(num);

	//feature[11] = 0;
	num = 0;
	for (i = 0; i < rect.height; i++) {
		if (rect.rect[i * rect.width + x1] == '0')
			num++;
	}
	feature.push_back(num);

	num = 0;
	for (i = 0; i < rect.height; i++) {
		if (rect.rect[i * rect.width + x2] == '0')
			num++;
	}
	feature.push_back(num);
}

double FEATURE::get_distance(const FEATURE &rect1)
{
	double ret = 0.0;
	for (int i = 0; i < 13; i++) {
		ret += (feature[i] - rect1.get_feature_dimensional(i)) * (feature[i] - rect1.get_feature_dimensional(i));
	}
	return sqrt(ret);
}

FEATURE2::FEATURE2(const COMP_RECT &rect)
{
	//int x1, x2, y1, y2;
	
	width = rect.width;
	height = rect.height;
	FEATURE2::rect = rect;

	int i;
	for (i = 0; i < sub_num; i++) {
		for (int j = 0; j < sub_num; j++) {
			int bn = 0;
			for (int k = height * i / sub_num; k < height * (i + 1) / sub_num; k++) {
				for (int n = width * j / sub_num; n < width * (j + 1) / sub_num; n++) {
					if (rect.rect[k * width + n] == '0') {
						bn++;
					}
				}
			}
			//feature[i * sub_num + j] = (double)bn / tn;
			//feature.push_back((double)bn / tn);
			feature.push_back((double)bn);
		}
	}

	for (i = 1; i < sub_num; i++) {
		int y = height * i / sub_num;
		//cout << "y=" << y << endl;
		int node = 0;
		for (int j = 0; j < width; j++) {
			if (rect.rect[y * width + j] == '0')
				node++;
		}
		feature.push_back((double)node);
	}
	for (i = 1; i < sub_num; i++) {
		int x = width * i / sub_num;
		//cout << "x=" << x << endl;
		int node = 0;
		for (int j = 0; j < height; j++) {
			if (rect.rect[j * width + x] == '0')
				node++;
		}
		feature.push_back((double)node);
	}
}

double FEATURE2::get_distance(const FEATURE2 &rect1)
{
	double ret = 0.0;
	int block = sub_num * sub_num + (sub_num - 1) * 2;
	for (int i = 0; i < block; i++) {
		//ret += (feature[i] - rect1.get_feature_dimensional(i)) * (feature[i] - rect1.get_feature_dimensional(i));
		ret += fabs(feature[i] - rect1.get_feature_dimensional(i));
	}
	//return sqrt(ret);
	return ret;
}

int FEATURE3::parseL(int x, int y)
{
	int l = y * width + x;
	int r = 0;

	if (rect.rect[l] == '0')
		r += 4;
	if (x + 1 < width)
		if (rect.rect[l + 1] == '0')
			r += 8;
	if (y + 1 < height)
		if (rect.rect[l + width] == '0')
			r += 2;
	if (x + 1 < width && y + 1 < height)
		if (rect.rect[l + width + 1] == '0')
			r += 1;

	return r;
}

FEATURE3::FEATURE3(const COMP_RECT &rect)
{
	width = rect.width;
	height = rect.height;
	FEATURE3::rect = rect;

	double lx[16] = {
		0.0, 0.5, 0.5, 1.0,
		0.5, 0.5, 0.0, 0.5,
		0.5, 0.0, 0.5, 0.5,
		1.0, 0.5, 0.5, 0.0
	};
	double ly[16] = {
		0.0, 0.5, 0.5, 0.0,
		0.5, 0.5, 1.0, 0.5,
		0.5, 1.0, 0.5, 0.5,
		0.0, 0.5, 0.5, 0.0
	};
	int w[16] = {0};

	{
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				w[parseL(x, y)]++;
			}
		}
	}

	double Lx = 0.0, Ly = 0.0;
	int i;
	for (i = 0; i < 16; i++) {
		Lx += lx[i] * w[i];
		Ly += ly[i] * w[i];
	}
	double b = 0.0;
	double Gy = 0.0, Gx = 0.0;
	{
		double a1 = 0.0, a2 = 0.0;
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				a1 += y * ((rect.rect[y * height + x] - '0') == 0 ? 1 : 0);
				b += ((rect.rect[y * height + x] - '0') == 0 ? 1 : 0);
				a2 += x * ((rect.rect[y * height + x] - '0') == 0 ? 1 : 0);
			}
		}
		Gy = a1 / b;
		Gx = a2 / b;
	}
	double thay = 0.0, thax = 0.0;
	{
		double b2 = 0.0;
		int y;
		for (y = 0; y < height; y++) {
			double b1 = 0.0;
			for (int x = 0; x < width; x++) {
				b1 += ((rect.rect[y * height + x] - '0') == 0 ? 1 : 0);
			}
			b2 += b1 * (y - Gy) * (y - Gy);
		}
		thay = sqrt(b2 / b);
		b2 = 0.0;
		for (int x = 0; x < width; x++) {
			double b1 = 0.0;
			for (y = 0; y < height; y++) {
				b1 += ((rect.rect[y * height + x] - '0') == 0 ? 1 : 0);
			}
			b2 += b1 * (x - Gx) * (x - Gx);
		}
		thax = sqrt(b2 / b);
	}
	double cx = Ly / thax;
	double cy = Lx / thay;
	feature.push_back(cx);
	feature.push_back(cy);
}

double FEATURE3::get_distance(const FEATURE3 &rect1)
{
	double ret = 0.0;
	//int block = sub_num * sub_num + (sub_num - 1) * 2;
	for (int i = 0; i < 2; i++) {
		ret += (feature[i] - rect1.get_feature_dimensional(i)) * (feature[i] - rect1.get_feature_dimensional(i));
		//ret += fabs(feature[i] - rect1.get_feature_dimensional(i));
	}
	//return sqrt(ret);
	return ret;
}
